using System;
using System.Collections.Generic;
using System.Linq;

namespace Rifts.Models
{
	public static class RandomExtension
	{

		public static int D4(this Random random)
		{
			return random.Next(1, 4 + 1);
		}

		public static int D6(this Random random)
		{
			return random.Next(1, 6 + 1);
		}


		private static int D(Random random, int max, int times)
		{
			var result = 0;
			for (int i = 0; i < times; i++)
				result += random.Next(1, max + 1);
			return result;
		}


		public static int D4(this Random random, int times)
		{
			return D(random, 4, times);
		}

		public static int D6(this Random random, int times)
		{
			return D(random, 6, times);
		}

		public static int Parse(this Random random, string roll)
		{
			var result = 0;
			var fragments = roll.Split('+');
			foreach (var fragment in fragments)
			{
				result += ParseFragment(random, fragment);
			}
			return result;
		}

		private static int ParseFragment(Random random, string roll)
		{
			if (random == null)
				throw new ArgumentNullException("random", "random is null.");
			if (String.IsNullOrEmpty(roll))
				throw new ArgumentException("roll is null or empty.", "roll");

			var fragments = roll.Split('*', 'x');
			var result = 1;
			foreach (var fragment in fragments)
				result = result * ParseFragment2(random, fragment);

			return result;
		}

		private static int ParseFragment2(Random random, string roll)
		{
			if (System.Text.RegularExpressions.Regex.IsMatch(roll, @"^\d+$"))
			{
				return int.Parse(roll);
			}
			if (System.Text.RegularExpressions.Regex.IsMatch(roll, @"^\d*D\d+$", System.Text.RegularExpressions.RegexOptions.IgnoreCase))
			{
				//TODO: Relearn how to use regex groups
				var fragments = roll.Split(new[] { 'D', 'd' }, StringSplitOptions.None);
				var max = int.Parse(fragments[1]);
				int times = 1;
				if (!string.IsNullOrEmpty(fragments[0]))
					times = int.Parse(fragments[0]);
				return D(random, max, times);
			}
			throw new FormatException("Cannot parse die roll " + roll);
		}
	}

	public static class MathEx
	{
		/// <summary>
		/// Adds nullable integers, replacing nulls with 0.
		/// </summary>
		/// <param name="a"></param>
		/// <param name="b"></param>
		/// <returns></returns>
		public static int? AddNull(this int? a, int? b)
		{
			return (a ?? 0) + (b ?? 0);
		}

		/// <summary>
		/// Adds nullable integers, replacing nulls with 0.
		/// </summary>
		/// <param name="a"></param>
		/// <param name="b"></param>
		/// <returns></returns>
		public static int? AddNull(this int? a, int b)
		{
			return (a ?? 0) + b;
		}
	}
}


